package com.cskaoyan.servlet;

import com.cskaoyan.bean.PageData;
import com.cskaoyan.bean.PageParameter;
import com.cskaoyan.bean.vo.BaseRespVo;
import com.cskaoyan.common.CommonServlet;
import com.cskaoyan.mapper.MarketStorageMapper;
import com.cskaoyan.model.MarketStorage;
import com.cskaoyan.service.StorageService;
import com.cskaoyan.service.impl.StorageServiceImpl;
import com.cskaoyan.utils.Constant;
import com.cskaoyan.utils.JacksonUtil;
import com.cskaoyan.utils.MyBatisUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.ibatis.session.SqlSession;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@MultipartConfig
@WebServlet("/admin/storage/*")
public class AdminStorageServlet extends CommonServlet {

    //成员变量
    String path;

    //service
    StorageService storageService = new StorageServiceImpl();

    @Override
    public void init() throws ServletException {
        path = (String) getServletContext().getAttribute(Constant.STORAGE_PATH);
    }

    //文件上传
    public BaseRespVo create(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求的报文中的信息
        Part part = request.getPart("file");
        String submittedFileName = part.getSubmittedFileName();
        long size = part.getSize();
        String key = UUID.randomUUID().toString() + submittedFileName.substring(submittedFileName.lastIndexOf("."));
        String url = "http://localhost:8083/admin/storage/fetch/" + key;
        String contentType = part.getContentType();

        MarketStorage storage = MarketStorage.builder()
                .key(key)
                .name(submittedFileName)
                .type(contentType)
                .size((int) size)
                .url(url)
                .addTime(new Date())
                .updateTime(new Date())
                .build();

        //获取字节输出流
        FileOutputStream outputStream = null;
        //获取字节输入流
        InputStream inputStream = null;
        try {
            outputStream = new FileOutputStream(new File(path, key));
            inputStream = part.getInputStream();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        int length = 0;
        byte[] bytes = new byte[1024];
        while ((length = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, length);
        }
        inputStream.close();
        outputStream.close();

        //保存文件信息到数据库
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        MarketStorageMapper storageMapper = sqlSession.getMapper(MarketStorageMapper.class);
        storageMapper.insertSelective(storage);
        sqlSession.commit();
        sqlSession.close();

        //发送JSON作为响应报文
        return BaseRespVo.ok(storage);
    }

    //访问已经上传的文件
    public void fetch(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String uri = request.getRequestURI();
        String fileName = uri.substring(uri.lastIndexOf("/") + 1);

        FileInputStream inputStream = null;
        ServletOutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(new File(path, fileName)); //先把文件从服务器磁盘读入内存
            outputStream = response.getOutputStream();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        int length = 0;
        byte[] bytes = new byte[1024];
        while ((length = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, length);
        }
        inputStream.close();
        outputStream.close();
    }

    public BaseRespVo list(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException {
        //1. 获取请求参数，注意PageParameter实体类装不下所有的请求参数，那就单独再获取两次，把请求参数获取完整
        Map<String, String[]> parameterMap = request.getParameterMap();
        //1.1 通过一个PageParameter封装这个请求参数
        PageParameter pageParameter = new PageParameter();
        //1.2 通过BeanUtils将请求参数封装到PageParameter
        BeanUtils.copyProperties(pageParameter, parameterMap);
        //1.3 请求参数中没有封装到pageParameter中的参数，我们再手动获取一次
        String key = request.getParameter("key");
        String name = request.getParameter("name");

        //2. 将请求参数传递给service，使用service调用对应的方法,然后返回响应报文中的data数据
        PageData data = storageService.list(pageParameter, key, name);

        //3.返回响应报文，通过BaseRespVo.ok()这个方法来封装数据
        return BaseRespVo.ok(data);
    }

    public BaseRespVo update(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1. 获取POST请求体中的数据，并封装为一个对象
        String jsonStr = request.getReader().readLine();
        //1.2 将请求体中的数据封装到MarketStorage对象中
        MarketStorage marketStorage = JacksonUtil.read(jsonStr, MarketStorage.class);

        //2. 通过service，将请求体中的数据封装对象传递到service相应的方法中，并返回数据作为响应报文中的data
        //注意：这一的请求报文中的请求体的数据和响应报文中的数据是一样的，我们可以直接利用请求体封装的对象返回
        storageService.update(marketStorage);

        //3. 返回响应报文中的data，并封装为一个BaseRespVo对象
        return BaseRespVo.ok(marketStorage);
    }

    public BaseRespVo delete(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1. 获取POST请求体中的数据
        String jsonStr = request.getReader().readLine();
        MarketStorage marketStorage = JacksonUtil.read(jsonStr, MarketStorage.class);

        //2. 调用service进行相应的删除操作
        storageService.delete(marketStorage);

        //3. 返回响应报文
        return BaseRespVo.ok(null);
    }
}
